package com.ckzp.jfinal.base;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.ckzp.core.ConfigUtil;
import com.ckzp.core.json.Jmode;
import com.ckzp.core.json.JsonUtil;
import com.jfinal.plugin.activerecord.*;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by 51594 on 2024/3/18.
 */
public abstract class MyModel<M extends MyModel> extends com.jfinal.plugin.activerecord.Model<M> {

    /**
     * 表名字
     */
    private String tableName;

    private String orderBy;

    /**
     * 查询条件
     */
    private List<Jmode> queryPara = new ArrayList();

    /**
     * 更新字段
     */
    private List<Jmode> updatePara = new ArrayList();

    /**
     * 清除参数
     *
     * @return
     */
    public M n() {
        queryPara.clear();
        updatePara.clear();
        orderBy = null;
        return (M) this;
    }

    /**
     * 增加查询条件
     *
     * @param field
     * @param value
     * @return
     */
    public M search(String field, Object value) {
        queryPara.add(Jmode.n().set("field", field).set("logic", "=").set("value", value));
        return (M) this;
    }

    /**
     * 增加查询条件
     *
     * @param field
     * @param logic
     * @param value
     * @return
     */
    public M search(String field, String logic, Object value) {
        queryPara.add(Jmode.n().set("field", field).set("logic", logic).set("value", value));
        return (M) this;
    }

    /**
     * 增加查询条件
     *
     * @param field
     * @param value
     * @return
     */
    public M setField(String field, Object value) {
        updatePara.add(Jmode.n().set("field", field).set("value", value));
        return (M) this;
    }


    /**
     * 增加排序
     *
     * @param orderBy
     * @return
     */
    public M orderBy(String orderBy) {
        this.orderBy = orderBy;
        return (M) this;
    }

    /**
     * 查询
     *
     * @return
     */
    public List doQuery() {
        TimeInterval time = DateUtil.timer();
        StrBuilder sb = StrBuilder.create();
        List values = new ArrayList();
        sb.append("select * from ").append(getTableName());
        if (queryPara.size() > 0) {
            sb.append(" where ");
            for (int k = 0; k < queryPara.size(); k++) {
                Jmode n = queryPara.get(k);
                if (k > 0) sb.append(" and ");
                sb.append(n.getStr("field")).append(n.getStr("logic")).append("?");
                values.add(n.get("value"));
            }
        }
        if (StrUtil.isNotBlank(orderBy)) sb.append(" order by " + orderBy);
        if (ConfigUtil.DEBUG()) {
            System.out.println("-----------------------find sql-------------------------------------------------");
            System.out.println("SQL:" + sb.toString());
            System.out.println("VALUE:" + values.toString());
        }
        List list = find(sb.toString(), values.toArray());
        if (ConfigUtil.DEBUG()) {
            System.out.println("USED:" + time.interval() + "ms");
            System.out.println("-----------------------find sql end---------------------------------------------");
        }
        return list;
    }


    /**
     * 查询
     *
     * @return
     */
    public int doDelete() {
        TimeInterval time = DateUtil.timer();
        StrBuilder sb = StrBuilder.create();
        List values = new ArrayList();
        sb.append("delete from ").append(getTableName());
        if (queryPara.size() > 0) {
            sb.append(" where ");
            for (int k = 0; k < queryPara.size(); k++) {
                Jmode n = queryPara.get(k);
                if (k > 0) sb.append(" and ");
                sb.append(n.getStr("field")).append(n.getStr("logic")).append("?");
                values.add(n.get("value"));
            }
        }
        if (ConfigUtil.DEBUG()) {
            System.out.println("-----------------------delete sql-------------------------------------------------");
            System.out.println("SQL:" + sb.toString());
            System.out.println("VALUE:" + values.toString());
        }
        int count = Db.delete(sb.toString(), values.toArray());
        if (ConfigUtil.DEBUG()) {
            System.out.println("USED:" + time.interval() + "ms");
            System.out.println("-----------------------delete sql end---------------------------------------------");
        }
        return count;
    }


    /**
     * 查询
     *
     * @return
     */
    public int doUpdate() {
        TimeInterval time = DateUtil.timer();
        if (updatePara.size() == 0) return 0;
        StrBuilder sb = StrBuilder.create();
        List values = new ArrayList();
        sb.append("update ").append(getTableName()).append(" set ");
        for (int k = 0; k < updatePara.size(); k++) {
            Jmode n = updatePara.get(k);
            sb.append(n.getStr("field")).append("=?");
            if (k < updatePara.size() - 1) sb.append(",");
            values.add(n.get("value"));
        }
        if (queryPara.size() > 0) {
            sb.append(" where ");
            for (int k = 0; k < queryPara.size(); k++) {
                Jmode n = queryPara.get(k);
                if (k > 0) sb.append(" and ");
                sb.append(n.getStr("field")).append(n.getStr("logic")).append("?");
                values.add(n.get("value"));
            }
        }
        if (ConfigUtil.DEBUG()) {
            System.out.println("-----------------------update sql-------------------------------------------------");
            System.out.println("SQL:" + sb.toString());
            System.out.println("VALUE:" + values.toString());
        }
        int count = Db.update(sb.toString(), values.toArray());
        if (ConfigUtil.DEBUG()) {
            System.out.println("USED:" + time.interval() + "ms");
            System.out.println("-----------------------update sql end---------------------------------------------");
        }
        return count;
    }

    /**
     * 查询第一个
     *
     * @return
     */
    public M queryFirst() {
        StrBuilder sb = StrBuilder.create();
        List<Object> values = new ArrayList();
        sb.append("select * from ").append(getTableName());
        if (queryPara.size() > 0) {
            sb.append(" where ");
            for (int k = 0; k < queryPara.size(); k++) {
                Jmode n = queryPara.get(k);
                if (k > 0) sb.append(" and ");
                sb.append(n.getStr("field")).append(n.getStr("logic")).append("?");
                values.add(n.get("value"));
            }
        }
        if (StrUtil.isNotBlank(orderBy)) sb.append(" order by " + orderBy);
        return super.findFirst(sb.toString(), values.toArray());
    }


    /**
     * 查询总数
     *
     * @return
     */
    public int queryCount() {
        StrBuilder sb = StrBuilder.create();
        List<Object> values = new ArrayList();
        sb.append("select count(*) from ").append(getTableName());
        if (queryPara.size() > 0) {
            sb.append(" where ");
            for (int k = 0; k < queryPara.size(); k++) {
                Jmode n = queryPara.get(k);
                if (k > 0) sb.append(" and ");
                sb.append(n.getStr("field")).append(n.getStr("logic")).append("?");
                values.add(n.get("value"));
            }
        }
        if (ConfigUtil.DEBUG()) {
            System.out.println("SQL:" + sb.toString());
            System.out.println("VALUE:" + values.toString());
        }
        return Db.queryInt(sb.toString(), values.toArray()).intValue();
    }

    /**
     * 分页查询
     *
     * @param ps
     * @return
     */
    public Page paginate(PageSearch ps) {
        TimeInterval time = DateUtil.timer();
        if (StrUtil.isNotBlank(ps.getGroupby())) {
            ps.sql_base.append(" group by " + ps.getGroupby());
        }
        if (StrUtil.isNotBlank(ps.orderby)) {
            ps.sql_base.append(" order by " + ps.orderby);
        }
        if (ConfigUtil.DEBUG()) {
            System.out.println("-----------------------search---------------------------------------------");
            System.out.println("pagenum         :" + ps.pagenum);
            System.out.println("pagesize        :" + ps.pagesize);
            System.out.println("select          :" + ps.sql_select);
            System.out.println("sql             :" + ps.sql_base.toString());
            System.out.println("value           :" + JsonUtil.toJsonString(ps.search_value));
        }
        Page page = super.paginate(ps.pagenum, ps.pagesize, ps.sql_select, ps.sql_base.toString(), ps.search_value.toArray());
        if (ConfigUtil.DEBUG()) {
            System.out.println("used            :" + time.interval());
            System.out.println("-----------------------search end---------------------------------------------");
        }
        return page;
    }

    /**
     * @param field
     * @param value
     * @return
     */
    public List findField(String field, Object value) {
        return find("select * from " + getTableName() + " where " + field + "=?", value);
    }

    /**
     * 根据指定列数据查询
     *
     * @param field
     * @param value
     * @return
     */
    public List findField(String field, Object value, String orderBy) {
        return find("select * from " + getTableName() + " where " + field + "=? order by " + orderBy, value);
    }

    /**
     * 根据指定列数据查询第一条
     *
     * @param field
     * @param value
     * @return
     */
    public M findFieldFirst(String field, Object value, String orderBy) {
        return findFirst("select * from " + getTableName() + " where " + field + "=? order by " + orderBy, value);
    }

    /**
     * 取表名
     *
     * @return
     */
    private String getTableName() {
        if (tableName == null) tableName = this._getTable().getName();
        return tableName;
    }


    /**
     * 带默认值的取int
     *
     * @param column
     * @param def
     * @return
     */
    public int getInt(String column, int def) {
        return getInt(column) == null ? def : getInt(column).intValue();
    }


    /**
     * 带默认值的取string
     *
     * @param column
     * @param def
     * @return
     */
    public String getStr(String column, String def) {
        return getStr(column) == null ? def : getStr(column).toString();
    }

    /**
     * 带默认值的取string
     *
     * @param column
     * @param def
     * @return
     */
    public double getDouble(String column, double def) {
        return getDouble(column) == null ? def : getDouble(column).doubleValue();
    }

    /**
     * 带默认值的取string
     *
     * @param column
     * @param def
     * @return
     */
    public long getLong(String column, long def) {
        return getLong(column) == null ? def : getLong(column).longValue();
    }

    public String getDateTime(String column) {
        return getDateTime(column, null);
    }


    public Date getDate(String column, DateTime def) {
        Date date = getDate(column);
        if (date == null) return def;
        return date;
    }


    public String getDateTime(String column, String def) {
        return getDate(column) == null ? def : DateUtil.format(getDate(column), "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 重写findbyid
     *
     * @param idValue
     * @return
     */
    public M findById(Object idValue) {
        String[] keys = TableMapping.me().getTable(this.getClass()).getPrimaryKey();
        if (keys.length > 0) {
            return this.findByIdLoadColumns((Object[]) (new Object[]{formatFieldValue(keys[0], idValue)}), "*");
        }
        return null;
    }


    /**
     * 重写
     * 自动转化格式
     *
     * @param attr
     * @param value
     * @return
     */
    public M set(String attr, Object value) {
        return super.set(attr, formatFieldValue(attr, value));
    }


    /**
     * 自动转化格式
     *
     * @param
     * @param column
     * @param value
     * @return
     */
    protected Object formatFieldValue(String column, Object value) {
        if (value == null) return null;
        Object colType = TableMapping.me().getTable(this.getClass()).getColumnType(column);
        if (colType == value.getClass()) return value;
        if (colType == Integer.class) {
            return NumberUtil.parseInt(String.valueOf(value));
        }
        if (colType == Double.class) {
            return NumberUtil.parseDouble(String.valueOf(value));
        }
        if (colType == Long.class) {
            return NumberUtil.parseLong(String.valueOf(value));
        }
        return value;
    }
}
